﻿using System.Diagnostics;
using DimensionsHelper.LanguageService.Syntax;

namespace DimensionsHelper.LanguageService.Symbols;

/// <summary>
///     原始语法节点的符号表，符号表中保存宏定义符号和其对应关系。
/// </summary>
public sealed class SourceSymbolTable : SymbolTable
{
    public SourceSymbolTable()
    {
        SymbolNameConflict += OnMacroSymbolConflict;
    }

    protected override Dictionary<string, ISymbol> Symbols { get; } = new();


    private static void OnMacroSymbolConflict(ISymbol symbol, ISymbol joinSymbol)
    {
        if (symbol is not MacroSymbol macroSymbol)
        {
            return;
        }

        macroSymbol.Redeclare(joinSymbol);
    }


    protected override bool DeclareSymbolCore(ISymbol symbol)
    {
        MacroSymbol? macroSymbol = symbol as MacroSymbol;
        Debug.Assert(macroSymbol != null && !string.IsNullOrWhiteSpace(macroSymbol.Name));
        if (Symbols.TryGetValue(macroSymbol.Name, out ISymbol? macro))
        {
            return ((MacroSymbol)macro).Redeclare(macroSymbol);
        }

        Symbols.Add(macroSymbol.Name, macroSymbol);
        return true;
    }


    /// <summary>
    ///     标记宏符号在指定位置使用#undef指令取消声明。取消后，在再次声明前，符号都是不可用的状态。
    /// </summary>
    /// <param name="name"></param>
    /// <param name="location"></param>
    public void CancelDeclaration(string name, SyntaxLocation location)
    {
        if (!Symbols.TryGetValue(name, out ISymbol? macro))
        {
            return;
        }

        ((MacroSymbol)macro).CancelDeclaration(location);
    }
}